package com.autonavi.yunda.yunji.common.web;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapExceptionCode;
import com.autonavi.yunda.yunji.common.exception.ExceptionLevel;
import com.autonavi.yunda.yunji.common.utils.http.RequestParser;
import com.autonavi.yunda.yunji.common.web.entity.GlobalResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

/**
 * @author cizhong.wcs
 * @date 2022/1/29 11:14 上午
 */
@Slf4j
@RestControllerAdvice
public class AmapWebExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public GlobalResponse<?> handlerMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String errorMessage = e.getBindingResult().getFieldErrors()
                .stream()
                .map(fieldError -> String.format("[%s: %s]\n", fieldError.getField(), fieldError.getDefaultMessage()))
                .collect(Collectors.joining());
        return GlobalResponse.errorResult(AmapExceptionCode.COMMON_ILLEGAL_PARAM.getCode(), errorMessage);
    }

    @ExceptionHandler(BindException.class)
    public GlobalResponse<?> handleBindException(BindException e) {
        String errorMessage = e.getBindingResult().getFieldErrors()
                .stream()
                .map(fieldError -> String.format("[%s: %s]\n", fieldError.getField(), fieldError.getDefaultMessage()))
                .collect(Collectors.joining());
        return GlobalResponse.errorResult(AmapExceptionCode.COMMON_ILLEGAL_PARAM.getCode(), errorMessage);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public GlobalResponse<?> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        String errorMessage = e.getMessage();
        return GlobalResponse.errorResult(AmapExceptionCode.COMMON_ILLEGAL_PARAM.getCode(), errorMessage);
    }

    @ExceptionHandler(AmapException.class)
    public static GlobalResponse<?> sendAmapErrorResponse(HttpServletRequest request, Exception exception) {
        AmapException amapException = (AmapException) exception;
        logException(amapException, getExceptionLogMsg(request, amapException));
        return GlobalResponse.errorResult(amapException.getExceptionCode().getCode(), amapException.getErrorMessage());
    }

    @ExceptionHandler(Exception.class)
    public static GlobalResponse<?> sendDefaultErrorResponse(HttpServletRequest request, Exception exception) {
        //todo 为了调试方便,先将exception 原有报错返回.
        log.error("request error", exception);
        return GlobalResponse.errorResult(AmapExceptionCode.COMMON_SERVER_ERROR.getCode(), exception.getMessage());
    }

    public static void logException(AmapException e, String msg) {
        if (e.getExceptionCode().getLevel() == ExceptionLevel.ERROR) {
            log.error(msg, e);
        } else if (e.getExceptionCode().getLevel() == ExceptionLevel.WARN) {
            log.warn(msg, e);
        } else {
            log.error(msg, e);
        }
    }

    public static String getExceptionLogMsg(HttpServletRequest request, AmapException e) {
        return String.format(
                "[Caught web exception] %s %s %s {%s %s %s}",
                RequestParser.getRemoteIp(request),
                request.getMethod(),
                request.getRequestURI(),
                e.getExceptionCode().getCode(),
                e.getExceptionCode().name(),
                e.getMessage());
    }
}
